package com.fau.wmbj.server.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fau.wmbj.server.audit.AuditingEntityListener;
import com.fau.wmbj.server.audit.CreatedDate;
import com.fau.wmbj.server.audit.LastModifiedDate;
import com.fau.wmbj.server.utils.Filter;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Where;

import javax.persistence.*;
import java.io.Serializable;
import java.util.*;

/**
 * 基类
 *
 * @author jiawei
 * @version 1.0
 * @datetime 2023-03-06 15:04
 */
@Getter
@Setter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"})
@Where(clause = " deleted = 0 ")
public abstract class BaseEntity<ID extends Serializable> implements Serializable {

    private static final long serialVersionUID = -67188388306700736L;

    public static final String ID_PROPERTY_NAME = "id";
    public static final String CREATED_DATE_PROPERTY_NAME = "createdDate";
    public static final String LAST_MODIFIED_DATE_PROPERTY_NAME = "lastModifiedDate";
    public static final String VERSION_PROPERTY_NAME = "version";

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "tableGenerator")
    @TableGenerator(name = "tableGenerator", table = "idgenerator", pkColumnName = "sequence_name",
            valueColumnName = "next_val",
            allocationSize = 1)
    private ID id;

    @CreatedDate
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Column(nullable = false, updatable = false, name = "create_time")
    private Date createdDate;

    @LastModifiedDate
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Column(nullable = false, name = "update_time")
    private Date lastModifiedDate;

    @Column(nullable = false, name = "deleted")
    private Boolean deleted = false;

    @Version
    @Column(nullable = false, name = "version")
    private Long version;

    @Transient
    private Map<String, Object> params = new HashMap<>();

    @Transient
    private List<Filter> filters = new ArrayList<>();

    /**
     * 判断是否为新建对象
     *
     * @return 是否为新建对象
     */
    @Transient
    public boolean isNew() {
        return getId() == null;
    }

    /**
     * 重写toString方法
     *
     * @return 字符串
     */
    @Override
    public String toString() {
        return String.format("Entity of type %s with id: %s", getClass().getName(), getId());
    }

    /**
     * 重写equals方法
     *
     * @param obj 对象
     * @return 是否相等
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!BaseEntity.class.isAssignableFrom(obj.getClass())) {
            return false;
        }
        BaseEntity<?> other = (BaseEntity<?>) obj;
        return getId() != null && getId().equals(other.getId());
    }

    /**
     * 重写hashCode方法
     *
     * @return HashCode
     */
    @Override
    public int hashCode() {
        int hashCode = 17;
        hashCode += getId() != null ? getId().hashCode() * 31 : 0;
        return hashCode;
    }

}
